architecture realization of test_environment is
	component processor is
		port (
			clock : in std_ulogic;
			reset : in std_ulogic;
			d_busout : out std_logic_vector(31 downto 0);
			d_busin : in std_logic_vector(31 downto 0);
			a_bus : out std_logic_vector(31 downto 0);
			write : out std_ulogic;
			read : out std_ulogic;
			ready : in std_ulogic;
			done : out std_ulogic;
			res : out std_logic_vector(31 downto 0)
		);
	end component processor;
    
    component memory
        generic (width: integer := 32; tpd: time := 1 ns);
		port (
        d_bus_out: out std_logic_vector(width-1 downto 0);
        d_bus_in : in  std_logic_vector(width-1 downto 0);
        a_bus    : in  std_logic_vector(width-1 downto 0);
        read     : in  std_ulogic;
        write    : in  std_ulogic;
        ready    : out std_ulogic
        );
	end component;
    
	signal clk, clk1, clk2: std_ulogic := '0';
	signal reset: std_ulogic;
	signal res1 : std_logic_vector(31 downto 0);
	signal res2 : std_logic_vector(31 downto 0);
	signal d_busout, d_busin, a_bus, d_busout2, d_busin2, a_bus2: std_logic_vector(31 downto 0);
	signal write, read, read2, write2, ready1, ready2: std_ulogic;
	signal done1, done2: std_ulogic;
	signal finished: boolean := false;
begin
	--bhv: entity work.processor(behaviour)
	bhv: processor
		port map (clk1, reset, d_busout, d_busin, a_bus, write, read, ready1, done1, res1);
	
	--bhv2: entity work.processor(behaviour)
	bhv2: processor
		port map (clk2, reset, d_busout2, d_busin2, a_bus2, write2, read2, ready2, done2, res2);
    
    tvc: memory
		port map (d_bus_out=>d_busin, d_bus_in=>d_busout,
                a_bus=>a_bus, read=>read, write=>write, ready=>ready1);
    
    tvc2: memory
		port map (d_bus_out=>d_busin2, d_bus_in=>d_busout2,
                a_bus=>a_bus2, read=>read2, write=>write2, ready=>ready2);
    
	clk <= not clk after 50 ns;
	clk1 <= clk when not finished and not (done2='0' and done1='1') else '1';
	clk2 <= clk when not finished and not (done2='1' and done1='0') else '1';
    
	--clk1 <= not clk1 after 50 ns when not finished and not (done2='0' and done1='1') else '1';
	--clk2 <= not clk2 after 50 ns when not finished and not (done2='1' and done1='0') else '1';
    
	reset <= '1', '0' after 400 ns;
	process
		procedure protocol(
			signal clk1, clk2, done1, done2: in std_ulogic;
			signal res1, res2: IN std_logic_vector(31 downto 0)) is
			variable done1zero, done2zero: boolean := false;
		begin
			--assert (done1='1') and (done2='1') report "a processor is busy!" severity warning;
			wait until falling_edge(clk1);
			lp0:loop
				wait until falling_edge(clk1);
				if done1='0' then done1zero := true; end if;
				if done2='0' then done2zero := true; end if;
				exit lp0 when done1zero and done2zero;
			end loop lp0;
            loop
                lp1:loop
                    wait until falling_edge(clk1) or falling_edge(clk2);
                    exit lp1 when (done1='1') and (done2='1');
                end loop lp1;
                assert std_match(res1,res2) report "mismatch in results" severity warning;
            end loop;
            end protocol;
		
	begin
		wait for 400 ns;
		wait until falling_edge(clk1);
		protocol(clk1, clk2, done1, done2, res1, res2);
		assert false report "simulation finished" severity warning;
		finished <= true;
		wait;
	end process;
	
end realization;